package com.quick.develop.flowable.service.definition.impl;

import cn.hutool.core.util.StrUtil;
import com.quick.develop.flowable.domain.vo.group.BpmGroupUserVO;
import com.quick.develop.framework.common.page.PageResult;
import com.quick.develop.framework.utils.PageUtils;
import com.quick.develop.framework.utils.uuid.IdUtils;
import com.quick.develop.flowable.domain.group.BpmGroupPageReqVO;
import com.quick.develop.flowable.framework.convert.definition.BpmGroupUserConvert;
import com.quick.develop.flowable.mapper.BpmGroupUserMapper;
import com.quick.develop.flowable.service.definition.IBpmGroupUserService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.IdentityService;
import org.flowable.idm.api.Group;
import org.flowable.idm.api.GroupQuery;
import org.flowable.idm.api.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static com.quick.develop.flowable.enums.BpmErrorCodeConstants.USER_GROUP_IS_EXISTS;
import static com.quick.develop.flowable.enums.BpmErrorCodeConstants.USER_GROUP_NOT_EXISTS;
import static com.quick.develop.framework.common.utils.ServiceExceptionUtils.exception;
import static com.quick.develop.framework.utils.collection.CollectionUtils.convertSet;


/**
 * @author junyuan.liu
 * @description: TODO
 * @date 2022/5/19 19:00
 */
@Service
@Validated
@Slf4j
public class BpmGroupUserServiceImpl  implements IBpmGroupUserService {
    @Resource
    private BpmGroupUserMapper bpmGroupUserMapper;

    @Resource
    private IdentityService identityService;

    @Override
    public PageResult<BpmGroupUserVO> getGroupUserPage(BpmGroupPageReqVO reqVO) {
        GroupQuery groupQuery = identityService.createGroupQuery();
        if (StrUtil.isNotBlank(reqVO.getName())){
            groupQuery.groupNameLikeIgnoreCase("%" + reqVO.getName() +"%");
        }
        if (StrUtil.isNotEmpty(reqVO.getType())){
            groupQuery.groupType(reqVO.getType());
        }
        List<Group> groups = groupQuery.orderByGroupName().asc().
                listPage(PageUtils.getStart(reqVO), reqVO.getPageSize());
        Set<String> groupIds = convertSet(groups, Group::getId);
        Map<String, List<User>> userMap = getGroupUserMap(groupIds);


        return new PageResult<>(BpmGroupUserConvert.INSTANCE.convertList(groups, userMap), groupQuery.count());
    }

    @Override
    public List<User> getUserByGroup(String id) {
        return identityService.createUserQuery().memberOfGroup(id).list();
    }

    @Override
    public List<BpmGroupUserVO> getGroupList(BpmGroupUserVO reqVo) {
        GroupQuery groupQuery = identityService.createGroupQuery();
        Optional.ofNullable(reqVo.getType()).ifPresent(groupQuery::groupType);
        List<Group> list = groupQuery.list();
        return BpmGroupUserConvert.INSTANCE.convert1(list);
    }

    @Override
    public void addGroupUser(BpmGroupUserVO reqVo) {
        GroupQuery groupQuery = identityService.createGroupQuery()
                .groupName(reqVo.getName());
        Optional.ofNullable(reqVo.getType()).ifPresent(groupQuery::groupType);
        long count = groupQuery.count();
        if (count != 0){
            throw exception(USER_GROUP_IS_EXISTS);
        }
        //创建组
        Group group = identityService.newGroup(IdUtils.randomUUID());
        BpmGroupUserConvert.INSTANCE.copyTo(reqVo, group);
        identityService.saveGroup(group);

        List<BpmGroupUserVO.GroupUser> userList = reqVo.getUserList();
        //用户不存在 创建用户 关联组
        userList.forEach(u -> {
            if (identityService.createUserQuery().userId(u.getId()).count() == 0){
                User user = identityService.newUser(u.getId());
                user.setDisplayName(u.getDisplayName());
                identityService.saveUser(user);
            }
            identityService.createMembership(u.getId(), group.getId());
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateGroupUser(BpmGroupUserVO reqVo) {
        long count = identityService.createGroupQuery().groupId(reqVo.getId()).count();
        if (count == 0){
            throw exception(USER_GROUP_NOT_EXISTS);
        }

        List<BpmGroupUserVO.GroupUser> userList = reqVo.getUserList();
        //先删除不存在组里面的用户
        bpmGroupUserMapper.delMembershipNotExist(reqVo);
        String groupId = reqVo.getId();
        //新增用户和组的关系
        userList.forEach(u -> {
            //用户不存在 先创建用户 再挂载组、用户关系
            if (identityService.createUserQuery().userId(u.getId()).count() == 0){
                createUserGroupShip(u, groupId);

            }else if (identityService.createUserQuery()
                    .userId(u.getId()).memberOfGroup(reqVo.getId()).count() == 0){
                //用户已存在 且用户没和组关联 先关联创建用户再关联组
                createUserGroupShip(u, groupId);
            }
        });

    }

    @Override
    public void deleteGroupUser(BpmGroupUserVO reqVo) {
        long count = identityService.createGroupQuery().groupId(reqVo.getId()).count();
        if (count == 0){
            throw exception(USER_GROUP_NOT_EXISTS);
        }
        //删除组 同时也删除关系
        identityService.deleteGroup(reqVo.getId());
    }

    /**
     * @description TODO 创建用户并创建组关系
     * @param reVo 用户
     * @param groupId 组ID
     * @author junyuan.liu
     * @date 2022/5/22 14:35
     */
    private void createUserGroupShip(BpmGroupUserVO.GroupUser reVo, String groupId){
        User user = identityService.newUser(reVo.getId());
        user.setDisplayName(reVo.getDisplayName());
        identityService.saveUser(user);
        identityService.createMembership(reVo.getId(), groupId);
    }

}
